/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "编辑骨骼.h"

#include <Context/节点数据操作.h>




static void f_从骨节更新编辑骨骼(S_物体* 根骨骼, S_物体** 骨节, uint32 depth, float32* 骨骼长度, const vec4& 父骨骼旋转, const float32 父骨骼长度) {
	//vec3 s = 骨节[骨骼->m_实例ID]->m_变换.location;
	uint32 num = 根骨骼->m_子物体.size();
	float32 最大长度 = 0;

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 骨骼 = 根骨骼->m_子物体[i];
		S_物体* 当前开始骨节;

		vec3 e = f_从骨头取末端骨节(骨骼)->m_变换.location;
		if (depth) {
			当前开始骨节 = f_从骨头取前端骨节(骨骼);
		}
		else {
			//s = 骨节[0]->m_变换.location;
			当前开始骨节 = 骨节[0];
		}
		vec3 s = 当前开始骨节->m_变换.location;
		vec3 骨骼方向 = e - s;



		float32 两骨节距离 = vec_normalize(&骨骼方向);
		骨骼长度[骨骼->m_实例ID] = 两骨节距离;

		最大长度 = DEF_Max(当前开始骨节->m_变换.scale.x, 两骨节距离);
		当前开始骨节->f_set缩放({ 最大长度, 最大长度, 最大长度 }, 0);




		骨骼方向 = f_graph_quat变换坐标(f_graph_quat反向(父骨骼旋转), 骨骼方向);
		vec4 q = f_graph_quat两向量(骨骼方向, { 0, 0, 1 });
		vec3 rot = f_graph_四元数转欧拉角(q);

		rot = vec3{ -rot.x, -rot.y, rot.z };
		if (depth) {
			骨骼->f_set位置({ 0, 0, 父骨骼长度 }, 0);
		}
		else {
			骨骼->f_set位置(s, 0);
		}


		骨骼->f_set旋转(rot, 0);
		骨骼->f_set缩放({ 1 ,1 ,1 }, 0);
		//两骨节距离 += 父骨骼长度;
		//骨骼方向 = f_graph_quat变换坐标(q, 骨骼方向);
		vec4 newQuat = f_graph_quatNormalize(f_graph_quat相乘(q, 父骨骼旋转));

		//骨骼->m_子物体[i]->f_set位置(骨骼->f_get位置() + vec3{ 0, 0, 1 }, 0);
		f_从骨节更新编辑骨骼(骨骼, 骨节, depth + 1, 骨骼长度, newQuat, 两骨节距离);
	}
}


static void f_将超出长度范围的骨节移动到范围内(S_物体* 根骨骼, S_物体** 骨节, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	uint32 num = 根骨骼->m_子物体.size();
	for (uint32 i = 0; i < num; ++i) {
		S_物体* 骨骼 = 根骨骼->m_子物体[i];
		S_物体* 当前开始骨节;

		vec3 e = f_从骨头取末端骨节(骨骼)->m_变换.location;
		if (depth) {
			当前开始骨节 = f_从骨头取前端骨节(骨骼);
		}
		else {
			//s = 骨节[0]->m_变换.location;
			当前开始骨节 = 骨节[0];
		}
		vec3 s = 当前开始骨节->m_变换.location;
		vec3 骨骼方向 = e - s;
		float32 两骨节距离 = vec_normalize(&骨骼方向);

		if (两骨节距离 > 骨骼长度[骨骼->m_实例ID] || 两骨节距离 < 骨骼长度[骨骼->m_实例ID]) {
			vec_mul(&骨骼方向, 两骨节距离 - 骨骼长度[骨骼->m_实例ID]);
			vec_sub(&(f_从骨头取末端骨节(骨骼)->m_变换.location), 骨骼方向);
			f_从骨头取末端骨节(骨骼)->m_isUpdate = true;
		}
		else {
			骨骼方向 = {};
		}

		f_将超出长度范围的骨节移动到范围内(骨骼, 骨节, depth + 1, 骨骼长度, 移动修正 + 骨骼方向);
	}
}


static vec3 f_将超出长度范围的骨节移动到范围内(S_物体* 当前骨骼, S_物体* 修正骨节, vec3& s, vec3& e, const float32* 骨骼长度) {
	vec3 骨骼方向 = e - s;
	float32 两骨节距离 = vec_normalize(&骨骼方向);

	if (两骨节距离 > 骨骼长度[当前骨骼->m_实例ID] || 两骨节距离 < 骨骼长度[当前骨骼->m_实例ID]) {
		vec_mul(&骨骼方向, 两骨节距离 - 骨骼长度[当前骨骼->m_实例ID]);
		vec_sub(&(修正骨节->m_变换.location), 骨骼方向);
		修正骨节->m_isUpdate = true;
	}
	else {
		骨骼方向 = {};
	}

	return 骨骼方向;
}
static void f_骨节更新子集骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	//S_物体* 当前骨骼 = (S_物体*)当前骨节->m_UserData;
	if (当前骨骼->m_Type == E_物体类型::t_骨架) {
		uint32 num = 当前骨骼->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			f_骨节更新子集骨骼((S_物体*)当前骨骼->m_子物体[i], depth + 1, 骨骼长度, 移动修正);
		}
	}
	else {
		vec3 骨骼方向 = {};
		if (depth) {
			vec3 s = f_从骨头取前端骨节(当前骨骼)->m_变换.location;
			vec3 e = f_从骨头取末端骨节(当前骨骼)->m_变换.location;

			骨骼方向 = f_将超出长度范围的骨节移动到范围内(当前骨骼, f_从骨头取末端骨节(当前骨骼), s, e, 骨骼长度);
		}
		

		uint32 num = 当前骨骼->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			f_骨节更新子集骨骼(当前骨骼->m_子物体[i], depth + 1, 骨骼长度, 移动修正 + 骨骼方向);
		}
	}

	
}
static void f_骨节更新父集骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	//S_物体* 当前骨骼 = ((S_物体*)(当前骨节->m_UserData))->m_父物体;
	//S_物体* 当前骨骼 = ((S_物体*)(当前骨节->m_UserData));
	if (当前骨骼->m_Type != E_物体类型::t_骨骼) {
		return;
	}


	vec3 s = f_从骨头取末端骨节(当前骨骼)->m_变换.location;
	vec3 e = f_从骨头取前端骨节(当前骨骼)->m_变换.location;

	vec3 骨骼方向 = f_将超出长度范围的骨节移动到范围内(当前骨骼, f_从骨头取前端骨节(当前骨骼), s, e, 骨骼长度);

	if (当前骨骼->m_父物体) {
		f_骨节更新父集骨骼(当前骨骼->m_父物体, depth + 1, 骨骼长度, 移动修正 + 骨骼方向);

		if (当前骨骼->m_父物体->m_子物体.size() > 1) {
			for (auto& 骨骼物体 : 当前骨骼->m_父物体->m_子物体) {
				if (骨骼物体 != 当前骨骼) {
					f_骨节更新子集骨骼(f_从骨头取前端骨节(骨骼物体), depth + 1, 骨骼长度, 移动修正 + 骨骼方向);
				}
			}
		}
	}
}

static void f_移动骨节更新骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	//递归到子集
	f_骨节更新子集骨骼(当前骨骼, 0, 骨骼长度, 移动修正);

	//递归到父级
	f_骨节更新父集骨骼(当前骨骼, 0, 骨骼长度, 移动修正);
}

static void f_旋转骨节更新骨骼(S_物体* 当前骨骼, uint32 depth, const float32* 骨骼长度, const vec3 移动修正) {
	vec3 s = f_从骨头取前端骨节(当前骨骼)->m_变换.location;
	vec3 e = f_从骨头取末端骨节(当前骨骼)->m_变换.location;

	vec3 骨骼方向 = f_将超出长度范围的骨节移动到范围内(当前骨骼, f_从骨头取末端骨节(当前骨骼), s, e, 骨骼长度);

	for (auto& 骨骼物体 : 当前骨骼->m_子物体) {

	}
}





void f_BE_从骨节更新骨骼(S_物体* 骨) {
	float32* 骨骼长度 = nullptr;
	S_物体* 骨骼 = 骨;
	if (骨->m_Type == E_物体类型::t_骨骼) {

	}
	else {
		骨骼 = ((S_物体*)(骨->m_UserData));
	}
	//return;
	//f_从骨节更新编辑骨骼(m_骨架物体, m_骨节物体->m_子物体.data(), 0, 骨骼长度, { 0,0,0,1 }, 0);
	if (!骨骼 || !骨骼->m_骨架) return;


	骨骼长度 = f_buf_F32_ptr(骨骼->m_骨架->m_骨骼长度);

	switch (f_prop_enum(S_节点数据状态::g_骨骼编辑模式)) {
		case E_骨骼编辑模式::e_物体模式: {
			break;
		}

		case E_骨骼编辑模式::e_姿态模式:
			switch (f_prop_enum(S_框架::g_骨骼姿态编辑模式)) {
			case E_骨骼姿态编辑模式::e_旋转模式:
				f_旋转骨节更新骨骼(骨骼, 0, 骨骼长度, {});
				break;
			case E_骨骼姿态编辑模式::e_拖拽模式:
				f_移动骨节更新骨骼(骨骼, 0, 骨骼长度, {});
				break;
			}
			break;

		case E_骨骼编辑模式::e_骨节编辑模式: {
			break;
		}
	}
	
}


void f_BE_从骨骼更新骨节(S_物体* 骨) {
	float32* 骨骼长度 = nullptr;
	S_物体* 骨骼 = 骨;
	if (骨->m_Type == E_物体类型::t_骨骼) {

	}
	else {
		骨骼 = ((S_物体*)(骨->m_UserData));
	}


	switch (f_prop_enum(S_节点数据状态::g_骨骼编辑模式)) {
	case E_骨骼编辑模式::e_物体模式: {
		break;
	}

	case E_骨骼编辑模式::e_姿态模式:
		//f_旋转骨节更新骨骼(骨骼, 0, 骨骼长度, {});
		break;
	case E_骨骼编辑模式::e_骨节编辑模式: {
		break;
	}
	}

}










